<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <!-- 写模板  -->
  <div id="root">
    <h3>b站视频链接https://www.bilibili.com/video/BV1LE411e7HE?p=19&spm_id_from=pageDriver</h3>
    <div>
      <p>{{name}}---{{message}}</p>
    </div>
    <p>name: {{name}}</p>
    <p>message: {{message}}</p>
  </div>

  <script>

    /*
    ctr: construct，构造器
    存在的问题：
    1. 只考虑到了单属性 {{name}} ，没有考虑到层级属性 {{obj.name.firstName}}
    2. 虚拟dom的处理
    */
    let rkuohao = /\{\{(.+?)\}\}/g;
    function compiler(template, data) {
      let childNodes = template.childNodes; // 获取子元素
      for(let i =0; i<childNodes.length; i++) {
        let type = childNodes[i].nodeType; //获取元素属性 1 元素，3 文本节点
        if(type === 3) {
          // 文本节点，可以判断里边是否有{{}} 插值
          let txt = childNodes[i].nodeValue; // 该属性只有文本节点才有意义
          // 判断有没有花括号
          txt = txt.replace(rkuohao, function(_, g) {
            let key = g.trim(); // 写在花括号里边的东西
            let value = data[key];
            return value;
          })

          // 注意： txt现在和dom元素是没有关系的
          childNodes[i].nodeValue = txt; // 将dom元素的{{}}替换成data中的数据
        } else if(type === 1) {
          // 子元素是元素，考虑它有没有子元素，是否需要将其子元素进行 插值替换
          compiler(childNodes[i], data)
        }
      }
    }

    function JGVue(options) {
      // 习惯（vue内部规范）内部使用的数据，私有的使用_开头，可读可写，只读数据$开头
      this._data = options.data;
      this._el = options.el;

      // 准备工作（准备模板)
      this._templateDom = document.querySelector(this._el)
       // el 的父元素，用于将真实dom替换
      this._parent = this._templateDom.parentNode;
      // 渲染工作
      this.render()
    }
    
    /* 将模板 结合 数据，得到真实dom添加到页面中 */ 
    JGVue.prototype.render = function() {
      this.compiler()
    }
    
    // 渲染模板,编译，将模板与数据结合得到真正的dom
    JGVue.prototype.compiler = function () {
      let realHTMLDom = this._templateDom.cloneNode(true)
      compiler(realHTMLDom, this._data)
      this.update(realHTMLDom)
    }

    // 将dom元素更新到页面中
    JGVue.prototype.update = function (real) {
      this._parent.replaceChild(real, document.querySelector('#root'))
    }

    // 参考vue的使用
    let app = new JGVue({
      el: '#root',
      data:{
        name: 'testname',
        message: 'info'
      }
    })



  </script>
</body>
</html>